home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-15  |  14.6 KB  |  659 lines

  1. #ifndef lint->”Sid = "$Id: util.c,v 1.10.2.1 1999/09/14 20:46:26 lhecking Exp $";
  2. #endif
  3.  
  4. /* GNUPLOT - util.c */
  5.  
  6. /*[
  7.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and
  12.  * that both that copyright notice and this permission notice appear
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the complete modified source code.  Modifications are to
  17.  * be distributed as patches to the released version.  Permission to
  18.  * distribute binaries produced by compiling modified sources is granted,
  19.  * provided you
  20.  *   1. distribute the corresponding source modifications from the
  21.  *    released version in the form of a patch file along with the binaries,
  22.  *   2. add special version identification to distinguish your version
  23.  *    in addition to the base release version number,
  24.  *   3. provide your name and address as the primary contact for the
  25.  *    support of your modified version, and
  26.  *   4. retain our contact information in regard to use of the base
  27.  *    software.
  28.  * Permission to distribute the released version of the source code along
  29.  * with corresponding source modifications in the form of a patch file is
  30.  * granted with same provisions 2 through 4 for binary distributions.
  31.  *
  32.  * This software is provided "as is" without express or implied warranty
  33.  * to the extent permitted by applicable law.
  34. ]*/
  35.  
  36.  
  37. #include "plot.h"
  38. #include "setshow.h"        /* for month names etc */
  39.  
  40.  
  41. /* TRUE if command just typed; becomes FALSE whenever we
  42.  * send some other output to screen.  If FALSE, the command line
  43.  * will be echoed to the screen before the ^ error message.
  44.  */
  45. TBOOLEAN screen_ok;
  46.  
  47. static char *num_to_str __PROTO((double r));
  48. static void parse_esc __PROTO((char *instr));
  49.  
  50. /*
  51.  * chr_in_str() compares the characters in the string of token number t_num
  52.  * with c, and returns TRUE if a match was found.
  53.  */
  54. int chr_in_str(t_num, c)
  55. int t_num;
  56. int c;
  57. {
  58.     register int i;
  59.  
  60.     if (!token[t_num].is_token)
  61.     return (FALSE);        /* must be a value--can't be equal */
  62.     for (i = 0; i < token[t_num].length; i++) {
  63.     if (input_line[token[t_num].start_index + i] == c)
  64.         return (TRUE);
  65.     }
  66.     return FALSE;
  67. }
  68.  
  69.  
  70. /*
  71.  * equals() compares string value of token number t_num with str[], and
  72.  *   returns TRUE if they are identical.
  73.  */
  74. int equals(t_num, str)
  75. int t_num;
  76. char *str;
  77. {
  78.     register int i;
  79.  
  80.     if (!token[t_num].is_token)
  81.     return (FALSE);        /* must be a value--can't be equal */
  82.     for (i = 0; i < token[t_num].length; i++) {
  83.     if (input_line[token[t_num].start_index + i] != str[i])
  84.         return (FALSE);
  85.     }
  86.     /* now return TRUE if at end of str[], FALSE if not */
  87.     return (str[i] == NUL);
  88. }
  89.  
  90.  
  91.  
  92. /*
  93.  * almost_equals() compares string value of token number t_num with str[], and
  94.  *   returns TRUE if they are identical up to the first $ in str[].
  95.  */
  96. int almost_equals(t_num, str)
  97. int t_num;
  98. char *str;
  99. {
  100.     register int i;
  101.     register int after = 0;
  102.     register int start = token[t_num].start_index;
  103.     register int length = token[t_num].length;
  104.  
  105.     if (!str)
  106.     return FALSE;
  107.     if (!token[t_num].is_token)
  108.     return FALSE;        /* must be a value--can't be equal */
  109.     for (i = 0; i < length + after; i++) {
  110.     if (str[i] != input_line[start + i]) {
  111.         if (str[i] != '$')
  112.         return (FALSE);
  113.         else {
  114.         after = 1;
  115.         start--;    /* back up token ptr */
  116.         }
  117.     }
  118.     }
  119.  
  120.     /* i now beyond end of token string */
  121.  
  122.     return (after || str[i] == '$' || str[i] == NUL);
  123. }
  124.  
  125.  
  126.  
  127. int isstring(t_num)
  128. int t_num;
  129. {
  130.  
  131.     return (token[t_num].is_token &&
  132.         (input_line[token[t_num].start_index] == '\'' ||
  133.          input_line[token[t_num].start_index] == '"'));
  134. }
  135.  
  136.  
  137. int isanumber(t_num)
  138. int t_num;
  139. {
  140.     return (!token[t_num].is_token);
  141. }
  142.  
  143.  
  144. int isletter(t_num)
  145. int t_num;
  146. {
  147.     return (token[t_num].is_token &&
  148.         ((isalpha((int)input_line[token[t_num].start_index])) ||
  149.          (input_line[token[t_num].start_index] == '_')));
  150. }
  151.  
  152.  
  153. /*
  154.  * is_definition() returns TRUE if the next tokens are of the form
  155.  *   identifier =
  156.  *              -or-
  157.  *   identifier ( identifer {,identifier} ) =
  158.  */
  159. int is_definition(t_num)
  160. int t_num;
  161. {
  162.     /* variable? */
  163.     if (isletter(t_num) && equals(t_num + 1, "="))
  164.     return 1;
  165.  
  166.     /* function? */
  167.     /* look for dummy variables */
  168.     if (isletter(t_num) && equals(t_num + 1, "(") && isletter(t_num + 2)) {
  169.     t_num += 3;        /* point past first dummy */
  170.     while (equals(t_num, ",")) {
  171.         if (!isletter(++t_num))
  172.         return 0;
  173.         t_num += 1;
  174.     }
  175.     return (equals(t_num, ")") && equals(t_num + 1, "="));
  176.     }
  177.     /* neither */
  178.     return 0;
  179. }
  180.  
  181.  
  182.  
  183. /*
  184.  * copy_str() copies the string in token number t_num into str, appending
  185.  *   a null.  No more than max chars are copied (including \0).
  186.  */
  187. void copy_str(str, t_num, max)
  188. char str[];
  189. int t_num;
  190. int max;
  191. {
  192.     register int i = 0;
  193.     register int start = token[t_num].start_index;
  194.     register int count = token[t_num].length;
  195.  
  196.     if (count >= max) {
  197.     count = max - 1;
  198.     FPRINTF((stderr, "str buffer overflow in copy_str"));
  199.     }
  200.  
  201.     do {
  202.     str[i++] = input_line[start++];
  203.     } while (i != count);
  204.     str[i] = NUL;
  205.  
  206. }
  207.  
  208. /* length of token string */
  209. int token_len(t_num)
  210. int t_num;
  211. {
  212.     return (token[t_num].length);
  213. }
  214.  
  215. /*
  216.  * quote_str() does the same thing as copy_str, except it ignores the
  217.  *   quotes at both ends.  This seems redundant, but is done for
  218.  *   efficency.
  219.  */
  220. void quote_str(str, t_num, max)
  221. char str[];
  222. int t_num;
  223. int max;
  224. {
  225.     register int i = 0;
  226.     register int start = token[t_num].start_index + 1;
  227.     register int count;
  228.  
  229.     if ((count = token[t_num].length - 2) >= max) {
  230.     count = max - 1;
  231.     FPRINTF((stderr, "str buffer overflow in quote_str"));
  232.     }
  233.     if (count > 0) {
  234.     do {
  235.         str[i++] = input_line[start++];
  236.     } while (i != count);
  237.     }
  238.     str[i] = NUL;
  239.     /* convert \t and \nnn (octal) to char if in double quotes */
  240.     if (input_line[token[t_num].start_index] == '"')
  241.     parse_esc(str);
  242. }
  243.  
  244.  
  245. /*
  246.  * capture() copies into str[] the part of input_line[] which lies between
  247.  * the begining of token[start] and end of token[end].
  248.  */
  249. void capture(str, start, end, max)
  250. char str[];
  251. int start, end;
  252. int max;
  253. {
  254.     register int i, e;
  255.  
  256.     e = token[end].start_index + token[end].length;
  257.     if (e - token[start].start_index >= max) {
  258.     e = token[start].start_index + max - 1;
  259.     FPRINTF((stderr, "str buffer overflow in capture"));
  260.     }
  261.     for (i = token[start].start_index; i < e && input_line[i] != NUL; i++)
  262.     *str++ = input_line[i];
  263.     *str = NUL;
  264. }
  265.  
  266.  
  267. /*
  268.  * m_capture() is similar to capture(), but it mallocs storage for the
  269.  * string.
  270.  */
  271. void m_capture(str, start, end)
  272. char **str;
  273. int start, end;
  274. {
  275.     register int i, e;
  276.     register char *s;
  277.  
  278.     e = token[end].start_index + token[end].length;
  279.     *str = gp_realloc(*str, (e - token[start].start_index + 1), "string");
  280.     s = *str;
  281.     for (i = token[start].start_index; i < e && input_line[i] != NUL; i++)
  282.     *s++ = input_line[i];
  283.     *s = NUL;
  284. }
  285.  
  286.  
  287. /*
  288.  *    m_quote_capture() is similar to m_capture(), but it removes
  289.  quotes from either end if the string.
  290.  */
  291. void m_quote_capture(str, start, end)
  292. char **str;
  293. int start, end;
  294. {
  295.     register int i, e;
  296.     register char *s;
  297.  
  298.     e = token[end].start_index + token[end].length - 1;
  299.     *str = gp_realloc(*str, (e - token[start].start_index + 1), "string");
  300.     s = *str;
  301.     for (i = token[start].start_index + 1; i < e && input_line[i] != NUL; i++)
  302.     *s++ = input_line[i];
  303.     *s = NUL;
  304.  
  305.     if (input_line[token[start].start_index] == '"')
  306.     parse_esc(*str);
  307.  
  308. }
  309.  
  310.  
  311. void convert(val_ptr, t_num)
  312. struct value *val_ptr;
  313. int t_num;
  314. {
  315.     *val_ptr = token[t_num].l_val;
  316. }
  317.  
  318. static char *num_to_str(r)
  319. double r;
  320. {
  321.     static int i = 0;
  322.     static char s[4][25];
  323.     int j = i++;
  324.  
  325.     if (i > 3)
  326.     i = 0;
  327.  
  328.     sprintf(s[j], "%.15g", r);
  329.     if (strchr(s[j], '.') == NULL &&
  330.     strchr(s[j], 'e') == NULL &&
  331.     strchr(s[j], 'E') == NULL)
  332.     strcat(s[j], ".0");
  333.  
  334.     return s[j];
  335. }
  336.  
  337. void disp_value(fp, val)
  338. FILE *fp;
  339. struct value *val;
  340. {
  341.     switch (val->type) {
  342.     case INTGR:
  343.     fprintf(fp, "%d", val->v.int_val);
  344.     break;
  345.     case CMPLX:
  346.     if (val->v.cmplx_val.imag != 0.0)
  347.         fprintf(fp, "{%s, %s}",
  348.             num_to_str(val->v.cmplx_val.real),
  349.             num_to_str(val->v.cmplx_val.imag));
  350.     else
  351.         fprintf(fp, "%s",
  352.             num_to_str(val->v.cmplx_val.real));
  353.     break;
  354.     default:
  355.     int_error("unknown type in disp_value()", NO_CARET);
  356.     }
  357. }
  358.  
  359.  
  360. double real(val)        /* returns the real part of val */
  361. struct value *val;
  362. {
  363.     switch (val->type) {
  364.     case INTGR:
  365.     return ((double) val->v.int_val);
  366.     case CMPLX:
  367.     return (val->v.cmplx_val.real);
  368.     }
  369.     int_error("unknown type in real()", NO_CARET);
  370.     /* NOTREACHED */
  371.     return ((double) 0.0);
  372. }
  373.  
  374.  
  375. double imag(val)        /* returns the imag part of val */
  376. struct value *val;
  377. {
  378.     switch (val->type) {
  379.     case INTGR:
  380.     return (0.0);
  381.     case CMPLX:
  382.     return (val->v.cmplx_val.imag);
  383.     }
  384.     int_error("unknown type in imag()", NO_CARET);
  385.     /* NOTREACHED */
  386.     return ((double) 0.0);
  387. }
  388.  
  389.  
  390.  
  391. double magnitude(val)        /* returns the magnitude of val */
  392. struct value *val;
  393. {
  394.     switch (val->type) {
  395.     case INTGR:
  396.     return ((double) abs(val->v.int_val));
  397.     case CMPLX:
  398.     return (sqrt(val->v.cmplx_val.real *
  399.              val->v.cmplx_val.real +
  400.              val->v.cmplx_val.imag *
  401.              val->v.cmplx_val.imag));
  402.     }
  403.     int_error("unknown type in magnitude()", NO_CARET);
  404.     /* NOTREACHED */
  405.     return ((double) 0.0);
  406. }
  407.  
  408.  
  409.  
  410. double angle(val)        /* returns the angle of val */
  411. struct value *val;
  412. {
  413.     switch (val->type) {
  414.     case INTGR:
  415.     return ((val->v.int_val >= 0) ? 0.0 : Pi);
  416.     case CMPLX:
  417.     if (val->v.cmplx_val.imag == 0.0) {
  418.         if (val->v.cmplx_val.real >= 0.0)
  419.         return (0.0);
  420.         else
  421.         return (Pi);
  422.     }
  423.     return (atan2(val->v.cmplx_val.imag,
  424.               val->v.cmplx_val.real));
  425.     }
  426.     int_error("unknown type in angle()", NO_CARET);
  427.     /* NOTREACHED */
  428.     return ((double) 0.0);
  429. }
  430.  
  431.  
  432. struct value *
  433.  Gcomplex(a, realpart, imagpart)
  434. struct value *a;
  435. double realpart, imagpart;
  436. {
  437.     a->type = CMPLX;
  438.     a->v.cmplx_val.real = realpart;
  439.     a->v.cmplx_val.imag = imagpart;
  440.     return (a);
  441. }
  442.  
  443.  
  444. struct value *
  445.  Ginteger(a, i)
  446. struct value *a;
  447. int i;
  448. {
  449.     a->type = INTGR;
  450.     a->v.int_val = i;
  451.     return (a);
  452. }
  453.  
  454.  
  455. void os_error(str, t_num)
  456. char str[];
  457. int t_num;
  458. {
  459. #ifdef VMS
  460.     static status[2] =
  461.     {1, 0};            /* 1 is count of error msgs */
  462. #endif /* VMS */
  463.  
  464.     register int i;
  465.  
  466.     /* reprint line if screen has been written to */
  467.  
  468.     if (t_num != NO_CARET) {    /* put caret under error */
  469.     if (!screen_ok)
  470.         fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
  471.  
  472.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  473.         (void) putc(' ', stderr);
  474.     for (i = 0; i < token[t_num].start_index; i++) {
  475.         (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
  476.     }
  477.     (void) putc('^', stderr);
  478.     (void) putc('\n', stderr);
  479.     }
  480.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  481.     (void) putc(' ', stderr);
  482.     fputs(str, stderr);
  483.     putc('\n', stderr);
  484.  
  485.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  486.     (void) putc(' ', stderr);
  487.     if (!interactive) {
  488.     if (infile_name != NULL)
  489.         fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
  490.     else
  491.         fprintf(stderr, "line %d: ", inline_num);
  492.     }
  493.  
  494.  
  495. #ifdef VMS
  496.     status[1] = vaxc$errno;
  497.     sys$putmsg(status);
  498.     (void) putc('\n', stderr);
  499. #else /* VMS */
  500.     fprintf(stderr, "(%s)\n\n", strerror(errno));
  501. #endif /* VMS */
  502.  
  503.     bail_to_command_line();
  504. }
  505.  
  506.  
  507. void int_error(str, t_num)
  508. char str[];
  509. int t_num;
  510. {
  511.     register int i;
  512.  
  513.     /* reprint line if screen has been written to */
  514.  
  515.     if (t_num != NO_CARET) {    /* put caret under error */
  516.     if (!screen_ok)
  517.         fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
  518.  
  519.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  520.         (void) putc(' ', stderr);
  521.     for (i = 0; i < token[t_num].start_index; i++) {
  522.         (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
  523.     }
  524.     (void) putc('^', stderr);
  525.     (void) putc('\n', stderr);
  526.     }
  527.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  528.     (void) putc(' ', stderr);
  529.     if (!interactive) {
  530.     if (infile_name != NULL)
  531.         fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
  532.     else
  533.         fprintf(stderr, "line %d: ", inline_num);
  534.     }
  535.     fputs(str, stderr);
  536.     fputs("\n\n", stderr);
  537.  
  538.     bail_to_command_line();
  539. }
  540.  
  541. /* Warn without bailing out to command line. Not a user error */
  542. void int_warn(str, t_num)
  543. char str[];
  544. int t_num;
  545. {
  546.     register int i;
  547.  
  548.     /* reprint line if screen has been written to */
  549.  
  550.     if (t_num != NO_CARET) {    /* put caret under error */
  551.     if (!screen_ok)
  552.         fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
  553.  
  554.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  555.         (void) putc(' ', stderr);
  556.     for (i = 0; i < token[t_num].start_index; i++) {
  557.         (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
  558.     }
  559.     (void) putc('^', stderr);
  560.     (void) putc('\n', stderr);
  561.     }
  562.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  563.     (void) putc(' ', stderr);
  564.     if (!interactive) {
  565.     if (infile_name != NULL)
  566.         fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
  567.     else
  568.         fprintf(stderr, "line %d: ", inline_num);
  569.     }
  570.     fprintf(stderr, "warning: %s\n", str);
  571.  
  572. }                /* int_warn */
  573.  
  574. /* Lower-case the given string (DFK) */
  575. /* Done in place. */
  576. void lower_case(s)
  577. char *s;
  578. {
  579.     register char *p = s;
  580.  
  581.     while (*p != NUL) {
  582.     if (isupper((int)*p))
  583.         *p = tolower(*p);
  584.     p++;
  585.     }
  586. }
  587.  
  588. /* Squash spaces in the given string (DFK) */
  589. /* That is, reduce all multiple white-space chars to single spaces */
  590. /* Done in place. */
  591. void squash_spaces(s)
  592. char *s;
  593. {
  594.     register char *r = s;    /* reading point */
  595.     register char *w = s;    /* writing point */
  596.     TBOOLEAN space = FALSE;    /* TRUE if we've already copied a space */
  597.  
  598.     for (w = r = s; *r != NUL; r++) {
  599.     if (isspace((int)*r)) {
  600.         /* white space; only copy if we haven't just copied a space */
  601.         if (!space) {
  602.         space = TRUE;
  603.         *w++ = ' ';
  604.         }            /* else ignore multiple spaces */
  605.     } else {
  606.         /* non-space character; copy it and clear flag */
  607.         *w++ = *r;
  608.         space = FALSE;
  609.     }
  610.     }
  611.     *w = NUL;            /* null terminate string */
  612. }
  613.  
  614.  
  615. static void parse_esc(instr)
  616. char *instr;
  617. {
  618.     char *s = instr, *t = instr;
  619.  
  620.     /* the string will always get shorter, so we can do the
  621.      * conversion in situ
  622.      */
  623.  
  624.     while (*s != NUL) {
  625.     if (*s == '\\') {
  626.         s++;
  627.         if (*s == '\\') {
  628.         *t++ = '\\';
  629.         s++;
  630.         } else if (*s == 'n') {
  631.         *t++ = '\n';
  632.         s++;
  633.         } else if (*s == 'r') {
  634.         *t++ = '\r';
  635.         s++;
  636.         } else if (*s == 't') {
  637.         *t++ = '\t';
  638.         s++;
  639.         } else if (*s == '\"') {
  640.         *t++ = '\"';
  641.         s++;
  642.         } else if (*s >= '0' && *s <= '7') {
  643.         int i, n;
  644.         if (sscanf(s, "%o%n", &i, &n) > 0) {
  645.             *t++ = i;
  646.             s += n;
  647.         } else {
  648.             /* int_error("illegal octal number ", c_token); */
  649.             *t++ = '\\';
  650.             *t++ = *s++;
  651.         }
  652.         }
  653.     } else {
  654.         *t++ = *s++;
  655.     }
  656.     }
  657.     *t = NUL;
  658. }
  659.